﻿using System;
using Autodesk.Revit.DB;
using YJKArchUtils.Utils;
using YJKGeometryFuncs;

namespace YJKArchUtils.StructurePoleSuit
{
	public class ColumnProfilePart : Structure2DPole
	{
		public int Number
		{
			get
			{
				return this.m_Number;
			}
			set
			{
				this.m_Number = value;
			}
		}

		public double ExtendLength
		{
			get
			{
				return this.m_ExtendLength;
			}
			set
			{
				if (this.ValidatingOfExtendLength(value))
				{
					this.m_ExtendLength = value;
				}
			}
		}

		public double WallLength
		{
			get
			{
				return this.m_WallLength;
			}
		}

		public bool Checked
		{
			get
			{
				return this.m_Checked;
			}
			set
			{
				this.m_Checked = value;
			}
		}

		private ColumnProfilePart()
		{
		}

		public ColumnProfilePart(ColumnProfilePart rhs) : base(rhs)
		{
			this.m_ComponentId = rhs.m_ComponentId;
			this.m_ptStart = rhs.m_ptStart;
			this.m_ptEnd = rhs.m_ptEnd;
			this.m_Bulge = rhs.m_Bulge;
			this.m_ptPositiveStart = rhs.m_ptPositiveStart;
			this.m_ptPositiveEnd = rhs.m_ptPositiveEnd;
			this.m_ptNegativeStart = rhs.m_ptNegativeStart;
			this.m_ptNegativeEnd = rhs.m_ptNegativeEnd;
			this.m_PositiveDirection = rhs.m_PositiveDirection;
			this.m_Number = rhs.m_Number;
			this.m_ExtendLength = rhs.m_ExtendLength;
			this.m_Checked = rhs.m_Checked;
			this.m_WallLength = rhs.WallLength;
			this.m_ptStartNodePosition = this.m_ptStart;
			this.m_ptEndNodePosition = this.m_ptEnd;
			this.m_VariableCross_SectionInPositiveStart = rhs.m_VariableCross_SectionInPositiveStart;
			this.m_VariableCross_SectionInPositiveEnd = rhs.m_VariableCross_SectionInPositiveEnd;
			this.m_VariableCross_SectionInNegativeStart = rhs.m_VariableCross_SectionInNegativeStart;
			this.m_VariableCross_SectionInNegativeEnd = rhs.m_VariableCross_SectionInNegativeEnd;
		}

		public ColumnProfilePart(ElementId componentId, XYZ ptStart, XYZ ptEnd, double bulge, XYZ ptPositiveStart, XYZ ptPositiveEnd, XYZ ptNegativeStart, XYZ ptNegativeEnd, bool positiveDirection, int number, double extendLength, bool isChecked) : base(componentId, ptStart, ptEnd, bulge, ptPositiveStart, ptPositiveEnd, ptNegativeStart, ptNegativeEnd, positiveDirection)
		{
			this.m_ComponentId = componentId;
			this.m_ptStart = ptStart;
			this.m_ptEnd = ptEnd;
			this.m_Bulge = bulge;
			this.m_ptPositiveStart = ptPositiveStart;
			this.m_ptPositiveEnd = ptPositiveEnd;
			this.m_ptNegativeStart = ptNegativeStart;
			this.m_ptNegativeEnd = ptNegativeEnd;
			this.m_PositiveDirection = positiveDirection;
			this.m_Number = number;
			this.m_Checked = isChecked;
			this.m_WallLength = base.Length();
			if (YJKGeometryFuncs.Geometry.LessThan(this.m_WallLength, extendLength))
			{
                this.m_ExtendLength = (base.PositiveHalfWidth + base.NegativeHalfWidth) / 2.0 + YJKArchUtils.Utils.Common.MMToFeet(100.0);
			}
			else
			{
				this.m_ExtendLength = extendLength;
			}
			this.m_ptStartNodePosition = this.m_ptStart;
			this.m_ptEndNodePosition = this.m_ptEnd;
		}

		public double CalculateInnerLength()
		{
			double num = base.Length();
			double num2;
			double num3;
			if (base.IsArcPole)
			{
				XYZ center = base.Center;
				double radius = base.Radius;
				double angle = YJKGeometryFuncs.Geometry.getAngle(center, this.m_ptPositiveStart);
				double angle2 = YJKGeometryFuncs.Geometry.getAngle(center, this.m_ptPositiveEnd);
				num2 = YJKGeometryFuncs.Geometry.BetweenTheAngles(angle, angle2, true) * radius;
				center.DistanceTo(this.m_ptNegativeStart);
				double angle3 = YJKGeometryFuncs.Geometry.getAngle(center, this.m_ptNegativeStart);
				double angle4 = YJKGeometryFuncs.Geometry.getAngle(center, this.m_ptNegativeEnd);
				num3 = YJKGeometryFuncs.Geometry.BetweenTheAngles(angle3, angle4, true) * radius;
			}
			else
			{
				num2 = base.PositiveSideLineLength();
				num3 = base.NegativeSideLineLength();
			}
			double result;
			if (YJKGeometryFuncs.Geometry.LessThan(num2, num3))
			{
				result = num - num2;
			}
			else
			{
				result = num - num3;
			}
			return result;
		}

		public void ResetEndWithCurve(XYZ ptCurNodePos, bool bIfWallSplit = false)
		{
			Structure2DPole._tagPositionType tagPositionType = base.TestPointPositionType(ptCurNodePos);
			if (tagPositionType == Structure2DPole._tagPositionType._StartNode)
			{
				if (!base.IsArcPole)
				{
					this.m_ptEnd = this.ResetEndWithLine(this.m_ptEnd, this.m_ptStart, this.GetNewLength(), bIfWallSplit);
				}
				else
				{
					XYZ center = base.Center;
					this.m_ptEnd = this.ResetEndWithArc(this.m_ptEnd, this.GetNewLength() - base.Length());
					this.m_Bulge = YJKGeometryFuncs.Geometry.GetBulge(this.m_ptStart, this.m_ptEnd, center, YJKGeometryFuncs.Geometry.LessThan(0.0, this.m_Bulge));
				}
				this.m_ptEndNodePosition = this.m_ptEnd;
			}
			else if (tagPositionType == Structure2DPole._tagPositionType._EndNode)
			{
				if (!base.IsArcPole)
				{
					this.m_ptStart = this.ResetEndWithLine(this.m_ptStart, this.m_ptEnd, this.GetNewLength(), bIfWallSplit);
				}
				else
				{
					XYZ center2 = base.Center;
					this.m_ptStart = this.ResetEndWithArc(this.m_ptStart, base.Length() - this.GetNewLength());
					this.m_Bulge = YJKGeometryFuncs.Geometry.GetBulge(this.m_ptStart, this.m_ptEnd, center2, YJKGeometryFuncs.Geometry.LessThan(0.0, this.m_Bulge));
				}
				this.m_ptStartNodePosition = this.m_ptStart;
			}
			this.UpdateSideline();
		}

		private double GetNewLength()
		{
			double num = this.CalculateInnerLength();
			return this.m_ExtendLength + num;
		}

		public void UpdateSideline()
		{
			if (!base.IsArcPole)
			{
				this.OffsetLine(this.m_ptStart, this.m_ptEnd, -base.PositiveHalfWidth, ref this.m_ptPositiveStart, ref this.m_ptPositiveEnd);
				this.OffsetLine(this.m_ptStart, this.m_ptEnd, base.NegativeHalfWidth, ref this.m_ptNegativeStart, ref this.m_ptNegativeEnd);
				return;
			}
			this.OffsetArc(this.m_ptStart, this.m_ptEnd, this.m_Bulge, base.PositiveHalfWidth, ref this.m_ptPositiveStart, ref this.m_ptPositiveEnd);
			this.OffsetArc(this.m_ptStart, this.m_ptEnd, this.m_Bulge, -base.NegativeHalfWidth, ref this.m_ptNegativeStart, ref this.m_ptNegativeEnd);
		}

		private void OffsetLine(XYZ ptStart, XYZ ptEnd, double offset, ref XYZ ptOffsetStart, ref XYZ ptOffsetEnd)
		{
			XYZ xyz = YJKGeometryFuncs.Geometry.RotateTo((ptEnd - ptStart).Normalize(), Math.PI*.5, XYZ.BasisZ) * offset;
			ptOffsetStart = ptStart + xyz;
			ptOffsetEnd = ptEnd + xyz;
		}

		private void OffsetArc(XYZ ptStart, XYZ ptEnd, double bugle, double offset, ref XYZ ptOffsetStart, ref XYZ ptOffsetEnd)
		{
			XYZ xyz = null;
			YJKGeometryFuncs.Geometry.GetCenterWithBulge(ptStart, ptEnd, bugle, ref xyz);
			double num = xyz.DistanceTo(ptStart) + offset;
			XYZ xyz2 = (ptStart - xyz).Normalize() * num;
			XYZ xyz3 = (ptEnd - xyz).Normalize() * num;
			ptOffsetStart = xyz + xyz2;
			ptOffsetEnd = xyz + xyz3;
		}

		protected XYZ ResetEndWithLine(XYZ ptChange, XYZ ptOther, double newLength, bool bIfWallSplit)
		{
            //if (!bIfWallSplit && YJKGeometryFuncs.Geometry.LessThan(Math.Abs(newLength), (base.PositiveHalfWidth + base.NegativeHalfWidth) / 2.0 + Common.MMToFeet(10.0)))
            //{
            //    return ptChange;
            //}
            //return ptOther + (ptChange - ptOther).Normalize() * newLength;

            if (!bIfWallSplit && YJKGeometryFuncs.Geometry.LessThan(Math.Abs(newLength), (base.PositiveHalfWidth + base.NegativeHalfWidth) / 2.0 + YJKArchUtils.Utils.Common.MMToFeet(10.0)))
            {
                return ptChange;
            }
            return ptOther + (ptChange - ptOther).Normalize() * newLength;
		}

		protected XYZ ResetEndWithArc(XYZ ptOld, double newLength)
		{
			double angle = newLength / base.Radius;
			XYZ center = base.Center;
			XYZ xyz = ptOld - center;
			XYZ axis = XYZ.BasisZ;
			if (YJKGeometryFuncs.Geometry.LessThan(base.Bulge, 0.0))
			{
				axis = -XYZ.BasisZ;
			}
			xyz = YJKGeometryFuncs.Geometry.RotateTo(xyz, angle, axis);
			return center + xyz.Normalize() * base.Radius;
		}

		public bool ValidatingOfExtendLength(double extendLength)
		{
			return !YJKGeometryFuncs.Geometry.LessThan(extendLength, 0.0);
		}

		private int m_Number;

		private double m_ExtendLength;

		private double m_WallLength;

		private bool m_Checked;
	}
}
